﻿using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

using HtmlHelp;
using HtmlHelp.ChmDecoding;
using OpenNETCF.Win32;


namespace CHMReader
{
    public partial class CHMReader : Form
    {
        private HtmlHelp.HtmlHelpSystem chm = null;
        private bool m_bInLoop = false;

        public CHMReader()
        {
            InitializeComponent();
        }

        private void menuItemExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }


        private void menuItemAbout_Click(object sender, EventArgs e)
        {
            this.Text = "";
            AboutDialog Dlg = new AboutDialog();
            this.Text = "CHMReader.NET";
            Dlg.ShowDialog();
        }

        private void menuItemOpen_Click(object sender, EventArgs e)
        {
            if (chm != null)
                chm = null;

            string FileName = "";
            Cursor.Current = Cursors.WaitCursor;
            OpenFileDialog Dlg = new OpenFileDialog();
            this.Text = "";
            Dlg.ShowDialog();
            this.Text = "CHMReader.NET";

            if (Dlg.DialogResult == DialogResult.OK)
            {
                Cursor.Current = Cursors.WaitCursor;
                FileName = Dlg.FileName;

                FileInfo Fi = new FileInfo(FileName);
                SaveInitialDir(Fi.DirectoryName);
                Update();
                OpenCHMFile(Fi);
                Fi = null;

                Cursor.Current = Cursors.Default;
            }
        }

        private string GetInitialDir()
        {
            string DefaultDir = @"\My Documents";
            string Dir = DefaultDir;
            OpenNETCF.Win32.RegistryKey RegKey = null;
            try
            {
                RegKey = OpenNETCF.Win32.Registry.CurrentUser.CreateSubKey("CHMReader");
                Dir = RegKey.GetValue("CHMDir", DefaultDir).ToString();
                RegKey.Close();
            }
            catch (Exception)
            {
                Dir = DefaultDir;
            }
            return Dir;
        }

        private void SaveInitialDir(string Dir)
        {
            OpenNETCF.Win32.RegistryKey RegKey = null;
            try
            {
                RegKey = OpenNETCF.Win32.Registry.CurrentUser.CreateSubKey("CHMReader");
                RegKey.SetValue("CHMDir", Dir);
                RegKey.Close();
            }
            catch (Exception)
            {
            }
        }

        private void OpenCHMFile(FileInfo CHMFileInfo)
        {
            if (!File.Exists(CHMFileInfo.FullName))
            {
                MessageBox.Show("Failed to find " + CHMFileInfo.FullName);
                return;
            }

            Cursor.Current = Cursors.WaitCursor;
            if (chm != null)
                chm = null;

            //txtTitle1.Text = txtTitle2.Text = txtTitle3.Text = CHMFileInfo.Name;

            //tabControl1.Enabled = true;
            //tabControl1.Visible = true;

            // Remove all Tab Pages
            //tabControl1.TabPages.Clear();
            Update();

            // Reset Contents 
            //m_bContentsInit = false;
            //tvContents.Nodes.Clear();

            // Reset Index
            //m_bIndexInit = false;
            //txtIndex.Text = "";
            //lbIndex.Items.Clear();

            // Reset Search
            //m_bSearchInit = false;
            //txtSearch.Text = "";
            //lvSearch.Items.Clear();

            // Init HTMLHelp System
            chm = new HtmlHelpSystem();

            /*
            // Check Allow CHB Files
            DumpingInfo dmpInfo = null;
            bool bDumpInfo = false;
            OpenNETCF.Win32.RegistryKey RegKey = null;
            try
            {
                RegKey = OpenNETCF.Win32.Registry.CurrentUser.CreateSubKey("CHMReader");
                int iInt = Convert.ToInt32(RegKey.GetValue("AllowCHB", 0));
                if (iInt != 0)
                    bDumpInfo = true;
                else
                    bDumpInfo = false;

            }
            catch (Exception)
            {
                RegKey.Close();
            }
            */
            // If enabled, create dump info		
            DumpingInfo dmpInfo = null;
            bool bDumpInfo = false;
            dmpInfo = new DumpingInfo(DumpingFlags.DumpBinaryIndex | DumpingFlags.DumpBinaryTOC | DumpingFlags.DumpFullText | DumpingFlags.DumpStrings | DumpingFlags.DumpTextIndex | DumpingFlags.DumpTextTOC | DumpingFlags.DumpTopics | DumpingFlags.DumpUrlStr | DumpingFlags.DumpUrlStr | DumpingFlags.DumpUrlTbl, CHMFileInfo.DirectoryName, DumpCompression.Maximum);
            dmpInfo.m_bAllowSaveDump = bDumpInfo;
            

            // Open CHM File.
            chm.OpenFile(CHMFileInfo.FullName, null);

            if (chm.HasTableOfContents)
            {
                tvContents.Nodes.Clear();
                foreach (TOCItem Item in chm.TableOfContents.TOC)
                {
                    FillTree(Item, tvContents.Nodes);
                }

                // Expand 2 levels of tree
                foreach (TOCItem Item in chm.TableOfContents.TOC)
                {
                    Item.treeNode.Expand();
                    foreach (TOCItem Child in Item.Children)
                    {
                        Child.treeNode.Expand();
                    }
                }
                tvContents.SelectedNode = tvContents.Nodes[0];
            }

            // Init the Tab Control
            //tabControl1.TabPages.Clear();
            //if (chm.HasTableOfContents)
            //{
            //    tabControl1.TabPages.Add(tabContents);
            //    tabContents.Text = "Contents";
            //    Update();
            //}
            //if (chm.HasIndex)
            //{
            //    tabControl1.TabPages.Add(tabIndex);
            //    tabIndex.Text = "Index";
            //    Update();
            //}
            //if (chm.FullTextSearch)
            //{
            //    tabControl1.TabPages.Add(tabSearch);
            //    tabSearch.Text = "Search";
            //    Update();
            //}

            // Select Contents as starting tab
            //tabControl1.SelectedIndex = -1;
            //tabControl1.SelectedIndex = tabControl1.TabPages.IndexOf(this.tabContents);

            // Restore Cursor
            Cursor.Current = Cursors.Default;
        }

        #region Build Contents Tree
        private TOCItem m_PrevItem = null;
        private void FillTree(TOCItem Item, TreeNodeCollection ParentNode)
        {
            string Name = Item.Name;
            TreeNode NewNode = new TreeNode(Name);
            NewNode.Tag = Item;

            if (m_PrevItem != null)
                m_PrevItem.Next = Item;

            Item.Prev = m_PrevItem;
            m_PrevItem = Item;

            Item.treeNode = NewNode;

            ParentNode.Add(NewNode);
            foreach (TOCItem ChildItem in Item.Children)
            {
                FillTree(ChildItem, NewNode.Nodes);
            }
        }
        #endregion

        #region Contents Handling
        private void tvContents_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
        {
            //if (m_bMovingSelection)
            //    return;

            if ((e.Action == TreeViewAction.Expand) || (e.Action == TreeViewAction.Collapse) || (e.Action == TreeViewAction.Unknown))
                return;

            //if (!m_bInLoop)
            //{
                TOCItem Item = (TOCItem)tvContents.SelectedNode.Tag;
                DisplayPage(Item.Url, tvContents.SelectedNode.Text, true);
            //}
        }
        #endregion


        private TOCItem FindTOCItem(string Url)
        {
            TOCItem item = (TOCItem)tvContents.Nodes[0].Tag;

            do
            {
                if (Url.StartsWith(@"../"))
                    Url = Url.Substring(3);
                else
                    break;
            }
            while (true);
            if (!Url.StartsWith("/"))
                Url = "/" + Url;

            while (item != null)
            {
                if (Url.Length <= item.Local.Length)
                {
                    if (item.Local.IndexOf(Url) >= item.Local.Length - Url.Length)
                        return item;
                }
                item = item.Next;
            }
            return null;
        }
        
		private void DisplayPage(string _Url, string Title)
		{
			DisplayPage(_Url, Title, false);
		}

		private void DisplayPage(string _Url, string Title, bool bEnableNavButtons)
		{
			string Url=_Url;
			bool bQuit=false;
			string HTMLText="";
			TOCItem item=null;
			
			if (_Url=="")
				return;
			
			do
			{
				HTMLView View=new HTMLView();
				View.NavButtons(bEnableNavButtons);

				m_bInLoop=true;
				Cursor.Current=Cursors.WaitCursor;								
								
				string CHMFileName="";
				string TopicName="";
				string Anchor="";
				if (!chm.BaseStream.GetCHMParts(Url,ref CHMFileName,ref TopicName, ref Anchor))
				{
					CHMFileName=chm.BaseStream.CHMFileName;
					TopicName=Url;
					Anchor="";
				}
				if ((TopicName=="") || (CHMFileName==""))
				{
					Cursor.Current=Cursors.Default;
					m_bInLoop=false;
					return;
				}
								
				HTMLText=chm.BaseStream.GetHTMLAndFiles(@"\temp\CHMTemp",Url);		
				if (HTMLText=="")
					View.SetHTMLText("Unspecified error displaying : "+Url);
				else if (HTMLText.StartsWith("#"))
					View.SetHTMLText(HTMLText.Substring(1));
				else
				{
					string path=@"\Temp\CHMTemp\CHMReader.htm";			
					if (File.Exists(path)) File.Delete(path);
					StreamWriter st=new StreamWriter(path);
					st.WriteLine(HTMLText);
					st.Close();

					if (Anchor!="")
						path+="#"+Anchor;
					View.SetUrl(@"file://"+path);
				}	
				View.SetTitle(@"\"+Title);				

				bool bLoop=false;
				do
				{
					bLoop=false;
					Cursor.Current=Cursors.Default;
					View.ShowDialogEx();
					View.Text="CHMReader.Net";
					Cursor.Current=Cursors.WaitCursor;

					TreeNode SNode=null;
					switch(View.WhereNext)
					{
						case EnumWhereNext.Next : 												
							SNode=tvContents.SelectedNode;
							item=(TOCItem)SNode.Tag;
							if ((item!=null) && (item.Next!=null))
							{
								Url=item.Next.Url;
								tvContents.SelectedNode=item.Next.treeNode;
								Title=item.Next.Name;
							}
							break;

						case EnumWhereNext.Prev : 
							SNode=tvContents.SelectedNode;
							item=(TOCItem)SNode.Tag;
							if ((item!=null) && (item.Prev!=null))
							{
								Url=item.Prev.Url;
								tvContents.SelectedNode=item.Prev.treeNode;
								Title=item.Prev.Name;
							}
							break;

						case EnumWhereNext.Close: 
							bQuit=true;
							break;

						case EnumWhereNext.None : 
							bQuit=true;
							break;

						case EnumWhereNext.Link:												
							Url=View.Link;

							// Handle Jump to anchor within local HTML File.
							if (Url.StartsWith("#"))
							{
								bLoop=true;
								View.SetAnchor(Url.Substring(1));
								Title="";
							}
							else
							{
								bLoop=false;
								item=FindTOCItem(Url);
								if (item!=null)
								{
									tvContents.SelectedNode=item.treeNode;
									Title=item.Name;
								}
							}
							break;
					}
				}
				while (bLoop==true);
				View.Dispose();
				View=null;
			}
			while(bQuit==false);
			m_bInLoop=false;					
			Cursor.Current=Cursors.Default;
		}

        private void menuItemView_Click(object sender, EventArgs e)
        {

        }
    }
}